﻿using MyCode.Project.Domain.Message.Response.EnterpriseWechat;
using MyCode.Project.Domain.Model;
using MyCode.Project.Domain.Repositories;
using MyCode.Project.Infrastructure.Common;
using MyCode.Project.OutSideService;
using MyCode.Project.Repositories;
using Senparc.CO2NET.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace MyCode.Project.Services.Implementation
{
    /// <summary>
    /// 员工档案与企业微信资料 相关服务
    /// </summary>
    public class StaffDataEnterpriseWechatService : ServiceBase , IStaffDataEnterpriseWechatService
    {
        private IWorkProcessService _workProcessService; 
        private ITBASSYSPARAMETERRepository _tBASSYSPARAMETERRepository;
        private readonly IEnterpriseWechatService _enterpriseWechatService;
        private IBasDepartmentRepository _basDepartmentRepository;
        private IBasEmployeeRepository _basEmployeeRepository;
        private IBasEmployeeDepartRepository _basEmployeeDepartRepository;
        private ITBDDEPARTMENTLRepository _tBDDEPARTMENTLRepository;
        private IRpEmployeeDepartLogRepository _rpEmployeeDepartLogRepository;
        private ITBDStaffDataLRepository _tBDStaffDataLRepository;
        private ITBDStaffDataRepository _tBDStaffDataRepository;

        private static object locker = new object(); //创建锁
        public StaffDataEnterpriseWechatService(IWorkProcessService workProcessService
            , ITBASSYSPARAMETERRepository tBASSYSPARAMETERRepository
            ,IBasDepartmentRepository basDepartmentRepository
            , IBasEmployeeRepository basEmployeeRepository
            , IBasEmployeeDepartRepository basEmployeeDepartRepository
            , ITBDDEPARTMENTLRepository tBDDEPARTMENTLRepository
            , IRpEmployeeDepartLogRepository rpEmployeeDepartLogRepository
            , ITBDStaffDataLRepository tBDStaffDataLRepository
            , ITBDStaffDataRepository tBDStaffDataRepository
            , IEnterpriseWechatService enterpriseWechatService)
        {
            _workProcessService = workProcessService;
            _tBASSYSPARAMETERRepository = tBASSYSPARAMETERRepository;
            _basEmployeeRepository = basEmployeeRepository;
            _basDepartmentRepository = basDepartmentRepository;
            _basEmployeeDepartRepository = basEmployeeDepartRepository;
            _enterpriseWechatService = enterpriseWechatService;
            _tBDDEPARTMENTLRepository = tBDDEPARTMENTLRepository;
            _rpEmployeeDepartLogRepository = rpEmployeeDepartLogRepository;
            _tBDStaffDataLRepository = tBDStaffDataLRepository;
            _tBDStaffDataRepository = tBDStaffDataRepository;
        }

        DateTime now = DateTime.Now;
        #region 初始化 公司-部门列表
        /// <summary>
        /// 初始化 公司-部门列表【后端测试用】
        /// </summary>
        /// <param name="query"></param>
        public void InitDepartment()
        {
            //var config = _companyConfigService.GetCompanyConfig(login.CompanyId);
            var configList = _tBASSYSPARAMETERRepository.Queryable().Where(t=>t.FPARAMETEROBJID== "GAT_HR_AbutmentParameter").ToList();
           
            configList.ForEach(SysParameter =>
            {
                WechatSysParameter config = new WechatSysParameter();
                if (!string.IsNullOrWhiteSpace(SysParameter.FPARAMETERS))
                {
                    try
                    {

                        XDocument xdoc = XDocument.Parse(SysParameter.FPARAMETERS);

                        // 使用 LINQ to XML 查询所有的 <name> 元素
                        var FCorpid = xdoc.Descendants("FCorpid").FirstOrDefault();
                        var FCorpsecret = xdoc.Descendants("FCorpsecret").FirstOrDefault();
                        
                        config.FAppid = FCorpid.Value;
                        config.FSecret = FCorpsecret.Value;
                    }
                    catch
                    {
                        return;
                    }
                    var infoList = _enterpriseWechatService.GetDepartmentList("", config.FAppid, config.FSecret);
                    var ids = infoList.Select(x => long.Parse(x.Id.ToString())).ToList();
                    var existsDepartList = _basDepartmentRepository.Queryable().Where(x => 1 == 1).ToList();
                    //_repository.UpdateQueue<BasDepartment>(x=>new BasDepartment { IsDelete=1},x=> x.IsDelete == 0 && x.CompanyId == login.CompanyId && !ids.Contains(x.Id));
                    List<BasDepartment> addList = new List<BasDepartment>();
                    infoList.ForEach(x =>
                    {
                        var info = existsDepartList.Where(p => p.WeChatId == x.Id).FirstOrDefault();
                        if (info == null)
                        {
                            BasDepartment depart = new BasDepartment();
                            depart.Id = Guid.NewGuid();
                            depart.WeChatId = x.Id;
                            depart.Name = x.Name;
                            depart.OrderNum = x.Order;
                            depart.WeChatIdParentId = x.Parentid;
                            addList.Add(depart);
                        }
                        else
                        {
                            now = now.AddSeconds(1);
                            _basDepartmentRepository.Update(p => new BasDepartment { Name = x.Name, OrderNum = x.Order, WeChatIdParentId = long.Parse(x.Parentid.ToString()), EditTime = now }, p => p.WeChatId == x.Id);

                        }

                        InitEmployee(config, x.Id);//员工列表


                        if (x.ListChild.Count() > 0)
                        {
                            addList.AddRange(SetChild(x.ListChild, existsDepartList, config));
                        }
                    });
                    if (addList.Count() > 0)
                        _basDepartmentRepository.Add(addList);


                    InitEmployeeInfo(config);//完善员工详情

                    //部门与员工的关系
                    SetEmployeeDepart(config);
                    _workProcessService.Add<IStaffDataEnterpriseWechatService>(this.MerchantId, "AddWechatVSKingDeeJob", "创建需要比对的数据任务", "", 2);
                }
            });
        }

        public List<BasDepartment> SetChild(List<DepartmentHasChild> listChild, List<BasDepartment> existsDepartList, WechatSysParameter config)
        {
            List<BasDepartment> addList = new List<BasDepartment>();
            List<long> dropList = new List<long>();
            var childids = listChild.Select(x => long.Parse(x.Id.ToString())).ToList();
            listChild.ForEach(t => {
                var info = existsDepartList.Where(p => p.WeChatId == t.Id).FirstOrDefault();
                var drop = existsDepartList.Where(x => x.WeChatIdParentId == t.Parentid && !childids.Contains(x.WeChatId.Value)).Select(x => x.WeChatId.Value).FirstOrDefault();
                if (drop > 0)
                    dropList.Add(drop);
                if (info == null)
                {
                    BasDepartment depart = new BasDepartment();
                    depart.Id = Guid.NewGuid();
                    depart.WeChatId = t.Id;
                    depart.Name = t.Name;
                    depart.OrderNum = t.Order;
                    depart.WeChatIdParentId = t.Parentid;
                    depart.EditTime = DateTime.Now;
                    addList.Add(depart);
                }
                else
                {
                    now = now.AddSeconds(1);
                    _basDepartmentRepository.Update(p => new BasDepartment { Name = t.Name, OrderNum = t.Order, WeChatIdParentId =long.Parse( t.Parentid.ToString()), EditTime = now }, p => p.WeChatId == t.Id);
                }
                if (t.ListChild.Count() > 0)
                {
                    addList.AddRange(SetChild(t.ListChild, existsDepartList, config));
                }
            });
            //已删掉的部门
            _basDepartmentRepository.Delete( x => dropList.Contains(x.WeChatId.Value));
            return addList;
        }
        #endregion

        #region 初始化 公司-公司-员工列表【后端测试用】
        /// <summary>
        /// 初始化 公司-公司-员工列表【后端测试用】
        /// </summary>
        /// <param name="query"></param>
        public void InitEmployee(WechatSysParameter config ,int departid)
        {
        
            var infoList = _enterpriseWechatService.GetDepartmentMemberList("", departid, config.FAppid, config.FSecret, 1);
            var existsempIds = _basEmployeeRepository.Queryable().Where(x => 1==1).Select(x => x.UserId).ToList();
            List<BasEmployee> addList = new List<BasEmployee>();
            infoList.Where(x => !existsempIds.Contains(x.Userid)).ToList().ForEach(x =>
            {
                BasEmployee employee = new BasEmployee();
                employee.ID = Guid.NewGuid();
                employee.UserId = x.Userid;
                employee.Name = EncryptHelper.Base64Encrypt(x.Name);
               
                employee.EditTime = DateTime.Now;
                
                addList.Add(employee);
            });
            if (addList.Count() > 0)
                _basEmployeeRepository.Add(addList);
             
        }
        #endregion

        #region 初始化 完善员工详情
        /// <summary>
        /// 初始化 完善员工详情【后端测试用】
        /// </summary>
        public void InitEmployeeInfo(WechatSysParameter config)
        {
           
            var empList = _basEmployeeRepository.Queryable().Where(x => 1==1).Select(x => x.UserId).ToList();
            empList.ForEach(x =>
            {
                var info = _enterpriseWechatService.GetEmployeeInfo(x, config.FAppid, config.FSecret);                
                if (info.Errcode == 60111)
                {
                    now = now.AddSeconds(1);
                    _basEmployeeRepository.Update(t => new BasEmployee
                    {
                        IsDelete = 1,
                      
                        EditTime = now
                    }, t => t.UserId == x );
                }
                else
                {
                    now = now.AddSeconds(1);
                    var openid = _enterpriseWechatService.GetOpenidByUserid(x, config.FAppid, config.FSecret);
                    _basEmployeeRepository.Update(t => new BasEmployee
                    {
                        Name = EncryptHelper.Base64Encrypt(info.name),
                        Nick = info.name,
                        Alias = info.alias,
                        Gender = info.gender,
                        Mobile = info.mobile,
                        Position = info.position,
                        Avatar = info.avatar,
                        ThumbAvatar = info.thumb_avatar,
                        Email = info.email,
                        Status = info.status,
                        OpenUserid = openid.openid,
                        EditTime = now
                    }, t => t.UserId == x);
                }
            });
            
        }
        #endregion

  
        #region 初始化 部门与员工的关系
        /// <summary>
        /// 初始化 部门与员工的关系
        /// </summary>
        /// <param name="login"></param>
        public void SetEmployeeDepart(WechatSysParameter config)
        {

            var departList = _basDepartmentRepository.Queryable().Where(x => 1 == 1).ToList();
            var employeeList = _basEmployeeRepository.Queryable().Where(x => 1 == 1).Select(x => new { x.ID, x.UserId ,x.Nick,x.OpenUserid}).ToList();
            var empShipList = _basEmployeeDepartRepository.Queryable().Where(x => 1==1).ToList();
            List<BasEmployeeDepart> emdepartList = new List<BasEmployeeDepart>();
            departList.ForEach(x =>
            {
                //获取目前部门的员工数据
                var empShip = empShipList.Where(p => p.DepartmentId == x.Id).ToList();
                //与同步过来后部门的员工数据对比
                var infoList = _enterpriseWechatService.GetDepartmentMemberList("", x.WeChatId.Value, config.FAppid, config.FSecret);
                var userids = empShip.Select(p => p.EmployeeUserId.Trim()).ToList();
                //新的关系则新增
                infoList.ForEach(t =>
                {
                    var em = employeeList.Where(f => f.UserId.Trim() == t.Userid.Trim()).FirstOrDefault();
                    if (em != null)
                    {
                        BasEmployeeDepart item = new BasEmployeeDepart();
                        item.Id =Guid.NewGuid();
                        item.DepartmentId = x.Id;
                        item.EmployeeId = em.ID;
                        item.EmployeeUserId = t.Userid;
                        item.KDepartementId = -1;
                        item.WechatDepartName = x.Name;
                        item.Nick = em.Nick;
                        item.OpenId = em.OpenUserid;
                        if (x.WeChatIdParentId > 1)
                        {
                            var pDept = departList.Where(s => s.WeChatId == x.WeChatIdParentId).FirstOrDefault();
                            if (pDept != null)
                            {
                                item.WechatDepartName = pDept.Name + "-" + item.WechatDepartName;
                                if (pDept.WeChatIdParentId > 1)
                                {
                                    pDept = departList.Where(s => s.WeChatId == pDept.WeChatIdParentId).FirstOrDefault();
                                    if (pDept != null)
                                    {
                                        item.WechatDepartName = pDept.Name + "-" + item.WechatDepartName;
                                        if (pDept.WeChatIdParentId > 1)
                                        {
                                            pDept = departList.Where(s => s.WeChatId == pDept.WeChatIdParentId).FirstOrDefault();
                                            if (pDept != null)
                                            {
                                                item.WechatDepartName = pDept.Name + "-" + item.WechatDepartName;
                                                if (pDept.WeChatIdParentId > 0)
                                                {

                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        emdepartList.Add(item);
                    }
                });
                ////已更换部门的员工则修改为删除状态
                //var infoUserIds = infoList.Select(p => p.Userid).ToList();
                //var upUserids = empShip.Where(p => !infoUserIds.Contains(p.EmployeeUserId)).Select(p => p.EmployeeUserId).ToList();
                //if (upUserids.Count() > 0)
                //    _basEmployeeDepartRepository.Delete( p => p.DepartmentId == x.Id && upUserids.Contains(p.EmployeeUserId));
            });
            if (emdepartList.Count() > 0)
            {
                _basEmployeeDepartRepository.Delete(t=>1==1);
                _basEmployeeDepartRepository.Add(emdepartList);
            }
            
        }
        #endregion

        #region AddWechatVSKingDeeJob(创建需要比对的数据任务)
        /// <summary>
        /// 创建需要比对的数据任务
        /// </summary>
        public void AddWechatVSKingDeeJob()
        {
            var list = _basEmployeeDepartRepository.Queryable().Where(t => 1 == 1).ToList();          
            List<RpEmployeeDepartLog> addList = new List<RpEmployeeDepartLog>();
            list.ForEach(t =>
            {
                t.Status = 0;
                t.OpenIdStatus = 0;
                t.DepartStatus = 0;
                RpEmployeeDepartLog temp = new RpEmployeeDepartLog();
                temp.Id = Guid.NewGuid();
                temp.Nick = t.Nick;                
                temp.CreateTime = DateTime.Now;
                temp.WechatDepartmentId = t.WechatDepartmentId;
                temp.WechatDepartName = t.WechatDepartName;
                temp.EmployeeId = t.EmployeeId;
                temp.EmployeeUserId = t.EmployeeUserId;
                temp.OpenId = t.OpenId;
                temp.Status = 0;
                temp.OpenIdStatus = 0;
                temp.DepartStatus = 0;
                addList.Add(temp);
            });
            _basEmployeeDepartRepository.Update(list);
            if (addList.Count > 0)
                _rpEmployeeDepartLogRepository.Add(addList);
            string now = DateTime.Now.ToString("yyyyMMdd");
            string lastMonth = DateTime.Now.AddMonths(-1).ToString("yyyyMMdd");
            string sql = $@"
IF EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_BD_StaffData{now}'
)
BEGIN
    PRINT '表 T_BD_StaffData{now} 存在';
END
ELSE
BEGIN
   select * into T_BD_StaffData{now}  from T_BD_StaffData
END;

IF EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'T_BD_StaffData{lastMonth}'
)
BEGIN
   drop table T_BD_StaffData{lastMonth};
END;
";
            _rpEmployeeDepartLogRepository.ExecuteSqlCommand(sql);
            _workProcessService.Add<IStaffDataEnterpriseWechatService>(this.MerchantId, "RunWechatVSKingDee", "执行需要比对的数据任务", "", 2);
        }

        #endregion


        #region RunWechatVSKingDee(执行需要比对的数据任务)
        /// <summary>
        /// 执行需要比对的数据任务
        /// </summary>
        public void RunWechatVSKingDee()
        {
            try
            {
                var allKingDepet = _tBDDEPARTMENTLRepository.Queryable().Where(t => 1 == 1).ToList();
                var allKingEmployeeL = _tBDStaffDataLRepository.Queryable().Where(t => 1 == 1).ToList();
                var allKingEmployee = _tBDStaffDataRepository.Queryable().Where(t => 1 == 1).ToList();
                var list = _rpEmployeeDepartLogRepository.Queryable().Where(t => t.Status == 0).OrderBy(t => t.SortNum).Take(1000).ToList();
                List<RpEmployeeDepartLog> addList = new List<RpEmployeeDepartLog>();
                list.ForEach(t =>
                {
                    //执行结果 -1=金蝶未找到员工  0=未开始   3=名字重复且部门无法匹配 100=更新完毕
                    int status = 0;
                    var KingEmployeeL = allKingEmployeeL.Where(h => h.FNAME.Trim() == t.Nick.Trim()).ToList();
                    if (KingEmployeeL.Count == 0)
                    {
                        status = -1;
                    }
                    else
                    {
                        //1 先找同名的人
                        //2 如果有超过1个同名人,则找相同部门
                        if (KingEmployeeL.Count == 1)
                        {
                            var tempOne = KingEmployeeL.FirstOrDefault();
                            var KingEmployee = allKingEmployee.FirstOrDefault(h => h.FID == tempOne.FID);
                            t.FID = KingEmployee.FID;
                                             
                            if (KingEmployee.FWECOMID != t.OpenId)
                            {

                                t.FWECOMID = KingEmployee.FWECOMID;
                                t.OpenIdStatus = 1;
                                KingEmployee.FWECOMID = t.OpenId;
                                _tBDStaffDataRepository.Update(KingEmployee);
                            }
                            else
                            {
                                t.OpenIdStatus = 100;
                            }
                            var KingDepart = allKingDepet.FirstOrDefault(h => h.FDEPTID == KingEmployee.FDEPARTMENTID);
                            if (KingDepart != null)
                            {
                                t.KDName = KingDepart.FNAME;
                                t.KDepartementId = KingDepart.FDEPTID;
                                if (KingDepart.FNAME != t.WechatDepartName)
                                {

                                    t.DepartStatus = 1;
                                }
                                else
                                    t.DepartStatus = 100;
                            }
                            else
                            {
                                t.KDName = "无部门";
                                t.DepartStatus = 1;
                            }

                            status = 100;
                        }
                        else if (KingEmployeeL.Count > 1)
                        {
                            var FIDList = KingEmployeeL.Select(h => h.FID).ToList();
                            var tempKingEmployee = allKingEmployee.Where(h => FIDList.Contains(h.FID)).ToList();
                            var tempDepartIdList = tempKingEmployee.Select(h => h.FDEPARTMENTID).ToList();
                            var tempKingDepet = allKingDepet.Where(h => tempDepartIdList.Contains(h.FDEPTID)).ToList();
                            var rightKingDepet = tempKingDepet.Where(h => h.FNAME == t.WechatDepartName).FirstOrDefault();
                            if (rightKingDepet == null) //多人同名但是部门无法匹配
                            {
                                t.KDName = string.Join(",", tempKingDepet.Select(h => h.FNAME).ToList());
                                var zaiZhiEmployeel = tempKingEmployee.Where(h => h.FEMPLOYEESTATUSID !=null &&h.FEMPLOYEESTATUSID.ToLower() != ("646b0211707080").ToLower()
                                && FIDList.Contains(h.FID)).ToList();
                                if (zaiZhiEmployeel.Count == 1)
                                {
                                    t.DepartStatus = 1;
                                    var tempOne = zaiZhiEmployeel.FirstOrDefault();
                                    var KingEmployee = allKingEmployee.FirstOrDefault(h => h.FID == tempOne.FID);
                                    t.FID = KingEmployee.FID;

                                    if (KingEmployee.FWECOMID != t.OpenId)
                                    {
                                        t.FWECOMID = KingEmployee.FWECOMID;
                                        t.OpenIdStatus = 1;
                                        KingEmployee.FWECOMID = t.OpenId;
                                        _tBDStaffDataRepository.Update(KingEmployee);
                                    }
                                    else
                                    {
                                        t.OpenIdStatus = 100;
                                    }
                                    var KingDepart = allKingDepet.FirstOrDefault(h => h.FDEPTID == KingEmployee.FDEPARTMENTID);
                                    if (KingDepart != null)
                                    {
                                        t.KDName = KingDepart.FNAME;
                                        t.KDepartementId = KingDepart.FDEPTID;
                                        if (KingDepart.FNAME != t.WechatDepartName)
                                        {

                                            t.DepartStatus = 1;
                                        }
                                        else
                                            t.DepartStatus = 100;
                                    }
                                    else
                                    {
                                        t.KDName = "无部门";
                                        t.DepartStatus = 1;
                                    }

                                    status = 100;
                                }
                                else
                                {
                                    t.DepartStatus = 1;
                                    status = 3;
                                }
                            }
                            else
                            {
                                t.KDName = rightKingDepet.FNAME;
                                t.KDepartementId = rightKingDepet.FDEPTID;
                                t.DepartStatus = 100;
                                var rightKingEmployee = tempKingEmployee.FirstOrDefault(h => h.FDEPARTMENTID == rightKingDepet.FDEPTID);
                                if (rightKingEmployee.FWECOMID != t.OpenId)
                                {
                                    t.FWECOMID = rightKingEmployee.FWECOMID;
                                    t.OpenIdStatus = 1;
                                    rightKingEmployee.FWECOMID = t.OpenId;
                                    _tBDStaffDataRepository.Update(rightKingEmployee);
                                }
                                else
                                {
                                    t.OpenIdStatus = 100;
                                }
                                status = 100;
                            }
                        }

                    }

                    t.Status = status;
                    var employeeDepart = _basEmployeeDepartRepository.Queryable().Where(h => h.EmployeeUserId == t.EmployeeUserId).First();
                    employeeDepart.Status = t.Status;
                    employeeDepart.OpenIdStatus = t.OpenIdStatus;
                    employeeDepart.DepartStatus = t.DepartStatus;
                    t.EditTime = DateTime.Now;
                    _basEmployeeDepartRepository.Update(employeeDepart);
                    _rpEmployeeDepartLogRepository.Update(t);

                });

            }
            catch (Exception ex)
            {
                throw new BaseException(ex.Message);
            }
            finally
            {
                if (_rpEmployeeDepartLogRepository.IsExist(t => t.Status == 0))
                {
                    _workProcessService.Add<IStaffDataEnterpriseWechatService>(this.MerchantId, "RunWechatVSKingDee", "执行需要比对的数据任务", "", 2);
                }

            }
            
        }

        #endregion

        /// <summary>
        /// 定时任务刷微信OPENID
        /// </summary>
        public void TaskAddOpenIdJob()
        {
            _workProcessService.Add<IStaffDataEnterpriseWechatService>(this.MerchantId, "InitDepartment", "刷企业微信数据", "", 2);            
        }

    }
}
